<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
    <meta name="description" content="Demonstration of large numbers of clipping planes.">
    <meta name="cesium-sandcastle-labels" content="Development">
    <title>Cesium Demo</title>
    <script type="text/javascript" src="../Sandcastle-header.js"></script>
    <script type="text/javascript" src="../../../Build/CesiumUnminified/Cesium.js" nomodule></script>
    <script type="module" src="../load-cesium-es6.js"></script>
</head>
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
    @import url(../templates/bucket.css);
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar">
    <table><tbody>
        <tr>
            <td>Distance</td>
            <td>
                <input type="range" min="-100.0" max="100.0" step="1.0" data-bind="value: cylinderRadius, valueUpdate: 'input'">
                <input type="text" size="5" data-bind="value: cylinderRadius">
            </td>
            <td>Plane Count</td>
            <td>
                <input type="range" min="1" max="128" step="1" data-bind="value: planeCount, valueUpdate: 'input'">
                <input type="text" size="5" data-bind="value: planeCount">
            </td>
        </tr>
    </tbody></table>
    <select data-bind="options: exampleTypes, value: currentExampleType"></select>
</div>
<script id="cesium_sandcastle_script">
function startup(Cesium) {
    'use strict';
//Sandcastle_Begin
var viewer = new Cesium.Viewer('cesiumContainer', {
    infoBox: false,
    selectionIndicator: false,
    shouldAnimate : true,
    projectionPicker : true,
    terrainProvider: Cesium.createWorldTerrain()
});

viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin);

var globe = viewer.scene.globe;
globe.depthTestAgainstTerrain = true;

var cylinderRadius = -20.0;
var radiusMultiplier = 1.0;

var steps = 32;
var clippingPlanes = [];
var modelEntityClippingPlanes;
var clippingModeUnion = false;
var enabled = true;

var clipObjects = ['model', 'b3dm', 'pnts', 'i3dm', 'terrain'];
var viewModel = {
    cylinderRadius : cylinderRadius,
    exampleTypes : clipObjects,
    currentExampleType : clipObjects[0],
    planeCount : steps
};

Cesium.knockout.track(viewModel);

var toolbar = document.getElementById('toolbar');
Cesium.knockout.applyBindings(viewModel, toolbar);

Cesium.knockout.getObservable(viewModel, 'cylinderRadius').subscribe(
    function(newValue) {
        cylinderRadius = parseFloat(viewModel.cylinderRadius);
        updatePlanes();
    }
);

Cesium.knockout.getObservable(viewModel, 'planeCount').subscribe(
    function(newValue) {
        var newSteps = parseFloat(viewModel.planeCount);
        if (newSteps !== steps) {
            steps = newSteps;
            modelEntityClippingPlanes.removeAll();
            computePlanes();
        }
    }
);

var scene = viewer.scene;
var planeEntities = [];
var selectedPlane;

function updatePlanes() {
    for (var i = 0; i < clippingPlanes.length; i++) {
        var plane = clippingPlanes[i];
        plane.distance = cylinderRadius * radiusMultiplier;
    }
}

function computePlanes() {
    var stepDegrees = Cesium.Math.TWO_PI / steps;
    clippingPlanes = [];

    for (var i = 0; i < steps; i++) {
        var angle = i * stepDegrees;
        var dir = new Cesium.Cartesian3();
        dir.x = 1.0;
        dir.y = Math.tan(angle);
        if (angle > Cesium.Math.PI_OVER_TWO) {
            dir.x = -1.0;
            dir.y *= -1.0;
        }
        if (angle > Cesium.Math.PI) {
            dir.x = -1.0;
        }
        if (angle > (Cesium.Math.PI_OVER_TWO * 3)) {
            dir.x = 1.0;
            dir.y = -dir.y;
        }
        Cesium.Cartesian3.normalize(dir, dir);
        var newPlane = new Cesium.ClippingPlane(dir, cylinderRadius * radiusMultiplier);
        modelEntityClippingPlanes.add(newPlane);
        clippingPlanes.push(newPlane);
    }
}

function createClippingPlanes(modelMatrix) {
    modelEntityClippingPlanes = new Cesium.ClippingPlaneCollection({
        modelMatrix : Cesium.defined(modelMatrix) ? modelMatrix : Cesium.Matrix4.IDENTITY,
        edgeWidth: 2.0,
        edgeColor: Cesium.Color.WHITE,
        unionClippingRegions : clippingModeUnion,
        enabled : enabled
    });
    computePlanes();
}

function updateClippingPlanes() {
    return modelEntityClippingPlanes;
}

var modelUrl = '../../SampleData/models/CesiumAir/Cesium_Air.glb';
var agiHqUrl = Cesium.IonResource.fromAssetId(40866);
var instancedUrl = '../../SampleData/Cesium3DTiles/Instanced/InstancedOrientation/tileset.json';
var pointCloudUrl = Cesium.IonResource.fromAssetId(5713);

function loadModel(url) {
    createClippingPlanes();
    var position = Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, 300.0);
    var heading = 0.0;
    var pitch = 0.0;
    var roll = 0.0;
    var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
    var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);
    var entity = viewer.entities.add({
        name : url,
        position : position,
        orientation : orientation,
        model : {
            uri : url,
            scale : 20,
            minimumPixelSize : 100.0,
            clippingPlanes : new Cesium.CallbackProperty(updateClippingPlanes, false)
        }
    });
    viewer.trackedEntity = entity;
}

var tileset;
function loadTileset(url, height) {
    createClippingPlanes();
    tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
        url : url,
        clippingPlanes : modelEntityClippingPlanes
    }));

    return tileset.readyPromise.then(function() {
        var boundingSphere = tileset.boundingSphere;

        var cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center);
        var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
        var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, height);
        var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
        tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);

        var radius = boundingSphere.radius;
        viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0.5, -0.2, radius * 4.0));
        viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
    }).otherwise(function(error) {
        throw(error);
    });
}

loadModel(modelUrl);

Cesium.knockout.getObservable(viewModel, 'currentExampleType').subscribe(function(newValue) {
    reset();

    if (newValue === clipObjects[0]) {
        // Model
        loadModel(modelUrl);
    } else if (newValue === clipObjects[1]) {
        // B3dm photogrammetry
        agiHqUrl.then(function(resource) {
            return loadTileset(resource, 0.0);
        });
    } else if (newValue === clipObjects[2]) {
        // Point clouds
        radiusMultiplier = 20.0;
        pointCloudUrl.then(function(resource) {
            return loadTileset(resource, 0.0);
        }).then(function() {
            tileset.pointCloudShading.attenuation = true;
        });
    } else if (newValue === clipObjects[3]) {
        // i3dm
        loadTileset(instancedUrl, 100.0);
    } else if (newValue === clipObjects[4]) {
        // Terrain
        var position = Cesium.Cartesian3.fromRadians(-2.0872979473351286, 0.6596620013036164, 2380.0);
        var entity = viewer.entities.add({
            position : position,
            model : {
                uri : '../../SampleData/models/CesiumMan/Cesium_Man.glb',
                minimumPixelSize : 128,
                scale : 40
            }
        });
        viewer.trackedEntity = entity;
        createClippingPlanes(entity.computeModelMatrix(Cesium.JulianDate.now()));
        globe.clippingPlanes = modelEntityClippingPlanes;
    }
    updatePlanes();
});

function reset() {
    radiusMultiplier = 1.0;
    viewModel.cylinderRadius = cylinderRadius;
    viewer.entities.removeAll();
    viewer.scene.primitives.removeAll();
    globe.clippingPlanes = undefined; // destroy Globe clipping planes, if any
    modelEntityClippingPlanes = undefined;
}

Sandcastle.addToggleButton('union', clippingModeUnion, function(checked) {
    clippingModeUnion = checked;
    modelEntityClippingPlanes.unionClippingRegions = clippingModeUnion;
});

Sandcastle.addToggleButton('enabled', enabled, function(checked) {
    enabled = checked;
    modelEntityClippingPlanes.enabled = enabled;
});

//Sandcastle_End
    Sandcastle.finishedLoading();
}
if (typeof Cesium !== 'undefined') {
    window.startupCalled = true;
    startup(Cesium);
}
</script>
</body>
</html>
